<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Description: 荧石开放平台接口封装
 *
 * @author      Eden
 * @datetime    2016/12/12 22:12
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */

final class Util_Ys
{

    /**
     * @var array 配置
     */
    private $conf = array();

    /**
     * @var array 数据
     */
    private $data = array();

    /**
     * @var string 错误
     */
    private $error = '';

    /**
     * @var null CI对象
     */
    private $ci = null;

    private $token = '';

    const TOKEN_URL = 'https://open.ys7.com/api/lapp/token/get';

    // 设备相关
    const D_ADD = 'https://open.ys7.com/api/lapp/device/add';
    const D_DELETE = 'https://open.ys7.com/api/lapp/device/delete';
    const D_EDIT_NAME = 'https://open.ys7.com/api/lapp/device/name/update';
    const D_CAPTURE = 'https://open.ys7.com/api/lapp/device/capture';
    const D_LIST = 'https://open.ys7.com/api/lapp/device/list';
    const D_INFO = 'https://open.ys7.com/api/lapp/device/info';
    const D_CAMERA = 'https://open.ys7.com/api/lapp/camera/list';
    const V_LIST = 'https://open.ys7.com/api/lapp/live/video/list';
    const V_LIMITED = 'https://open.ys7.com/api/lapp/live/address/limited';

    /**
     * 初始化
     */
    public function __construct()
    {
        $this->ci = & get_instance();
        $this->ci->load->driver('cache');

        if ($token = $this->ci->cache->redis->get('API:YS:Token')) {
            $this->token = $token;
        } else {
            $this->conf = $this->_getKeys();
            if (empty($this->conf)) {
                throw new Exception('配置错误');
            }
            $this->getToken();
        }
    }

    // =============================================
    // 接口

    /**
     * 获取令牌
     */
    public function getToken()
    {
        $response = request(self::TOKEN_URL, array(
            'appKey' => $this->conf['appKey'],
            'appSecret' => $this->conf['appSecret']
        ), 'POST');
        $res = $this->_after($response);
        if (!$res) {
            throw new Exception('无法交换令牌');
        }
        $val = $this->getData();
        $this->token = $val['accessToken'];
        $time = $val['expireTime'] / 1000;
        $time = $time - time();
        $this->ci->cache->redis->save('API:YS:Token', $this->token, intval($time));
    }

    /**
     * 添加设备
     * @param string $deviceSerial
     * @param string $validateCode
     * @return bool
     */
    public function deviceAdd($deviceSerial = '', $validateCode = '')
    {
        $response = request(self::D_ADD, array(
            'accessToken' => $this->token,
            'validateCode' => $validateCode,
            'deviceSerial' => $deviceSerial
        ), 'POST');
        return $this->_after($response);
    }

    /**
     * 删除设备
     * @param string $deviceSerial
     * @return bool
     */
    public function deviceDelete($deviceSerial = '')
    {
        $res = request(self::D_DELETE, array(
            'accessToken' => $this->token,
            'deviceSerial' => $deviceSerial
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 修改设备名称
     * @param string $deviceSerial
     * @param string $deviceName
     * @return bool
     */
    public function deviceEditName($deviceSerial = '', $deviceName = '')
    {
        $res = request(self::D_EDIT_NAME, array(
            'accessToken' => $this->token,
            'deviceSerial' => $deviceSerial,
            'deviceName' => $deviceName,
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 设备抓拍图片（封面图有用）
     * 含 data 值,需额外获取
     * @param string $deviceSerial
     * @param int $channelNo 通道号，IPC设备填写1
     * @return bool
     */
    public function deviceCapture($deviceSerial = '', $channelNo = 1)
    {
        $res = request(self::D_CAPTURE, array(
            'accessToken' => $this->token,
            'deviceSerial' => $deviceSerial,
            'channelNo' => $channelNo
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 获取设备列表
     * 含 data 值
     * @param int $pageStart
     * @param int $pageSize
     * @return bool
     */
    public function deviceList($pageStart = 0, $pageSize = 20)
    {
        $res = request(self::D_LIST, array(
            'accessToken' => $this->token,
            'pageStart' => $pageStart,
            'pageSize' => $pageSize
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 单个设备详情
     * @param string $deviceSerial
     * @return bool
     */
    public function deviceInfo($deviceSerial = '')
    {
        $res = request(self::D_INFO, array(
            'accessToken' => $this->token,
            'deviceSerial' => $deviceSerial
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 获取摄像头列表
     * @param int $pageStart
     * @param int $pageSize
     * @return bool
     */
    public function deviceCameraList($pageStart = 0, $pageSize = 20)
    {
        $res = request(self::D_CAMERA, array(
            'accessToken' => $this->token,
            'pageStart' => $pageStart,
            'pageSize' => $pageSize
        ), 'POST');
        return $this->_after($res);
    }

    /**
     * 获取用户下直播视频列表
     * @param int $pageStart
     * @param int $pageSize
     * @return bool
     */
    public function videoLists($pageStart = 0, $pageSize = 50)
    {
        $res = request(self::V_LIST, array(
            'accessToken' => $this->token,
            'pageStart' => $pageStart,
            'pageSize' => $pageSize
        ), "POST");
        return $this->_after($res);
    }

    /**
     * 有效的直播地址
     * @param string $deviceSerial
     * @param int $channelNo
     * @param string $expireTime
     * @return bool
     */
    public function videoAddressLimited($deviceSerial = '', $channelNo = 1, $expireTime = '')
    {
        $res = request(self::V_LIMITED, array(
            'accessToken' => $this->token,
            'deviceSerial' => $deviceSerial,
            'channelNo' => $channelNo,
            'expireTime' => empty($expireTime) ? 2592000 : intval($expireTime)
        ), 'POST');
        return $this->_after($res);
    }


    // =============================================



    /**
     * 获取配置
     * @return bool|mixed
     */
    private function _getKeys(){
        $ci = & get_instance();
        $query = $ci->db->get_where('setting', array(
            'use' => 'system',
            'key' => 'stream'
        ));
        if ($res = $query->row_array()) {
            try {
                $res = json_decode($res['value'], true);
                if (!empty($res['appKey']) && !empty($res['appSecret'])) {
                    return $res;
                }
            } catch(Exception $e) {}
        }
        return false;
    }

    /**
     * 处理返回数据
     * @param array $response
     * @return bool
     * @throws Exception
     */
    private function _after($response = array())
    {
        if (!empty($response) && !empty($response['data']) && $response['httpCode'] == 200) {
            try {
                $res = json_decode($response['data'], true);
                if (!empty($res) && is_array($res) && $res['code'] == 200) {
                    $this->data = !empty($res['data']) ? $res['data'] : array();
                    return true;
                }
                $error = !empty($res['msg']) ? $res['msg'] : '返回数据错误';
                $this->setError($error);
            } catch(Exception $e) {}
        }
        return false;
    }

    /**
     * 设置错误消息
     * @param string $error
     */
    private function setError($error = '')
    {
        $this->error = $error;
    }

    /**
     * 获取错误消息
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * 获取值
     * @return array
     */
    public function getData()
    {
        return $this->data;
    }
}
